﻿using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace X.LOG
{

        /// <summary>
        /// JSON序列化和反序列化辅助类
        /// </summary>
        internal static class JsonHelper
        {
            /// <summary>
            /// 任意对象序列化
            /// </summary>
            /// <param name="obj">对象</param>
            /// <param name="retain">保留属性</param>
            /// <param name="ignore">忽略属性</param>
            /// <param name="turns">要转换的属性</param>
            /// <returns>返回数据</returns>
            public static string Serialize(object obj,
                string[] retain = null,
                string[] ignore = null,
                IDictionary<string, string> turns = null)
            {
                var settings = new JsonSerializerSettings();

                if (retain != null || ignore != null || turns != null)
                {
                    // 设置序列化解析器
                    settings.ContractResolver = new CustomContractResolver(retain, ignore, turns);
                }

                // 设置序列化时间格式
                IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
                timeConverter.DateTimeFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";
                settings.Converters.Add(timeConverter);

                return JsonConvert.SerializeObject(obj, Formatting.Indented, settings);
            }

            /// <summary>
            /// 表格序列化
            /// </summary>
            /// <param name="rows">数据总行数</param>
            /// <param name="obj">对象</param>
            /// <param name="retain">保留属性</param>
            /// <param name="ignore">忽略属性</param>
            /// <param name="turns">要转换的属性</param>
            /// <returns>返回数据</returns>
            public static string Grid(object obj, int count,
                string[] retain = null,
                string[] ignore = null,
                IDictionary<string, string> turns = null)
            {
                return Serialize(new { total = count, rows = obj }, retain, ignore, turns);
            }

            /// <summary>
            /// 反序列化
            /// </summary>
            /// <typeparam name="T">要返回的类型</typeparam>
            /// <param name="obj">数据</param>
            /// <returns>返回对象</returns>
            public static T Deserialize<T>(string obj)
            {
                return JsonConvert.DeserializeObject<T>(obj);
            }


            /// <summary>
            /// 自定义序列化解析器
            /// </summary>
            public class CustomContractResolver : DefaultContractResolver
            {
                string[] retain = null;
                string[] ignore = null;
                IDictionary<string, string> turns = null;

                /// <summary>
                /// 构造函数
                /// </summary>
                /// <param name="retain">保留属性</param>
                /// <param name="ignore">忽略属性</param>
                /// <param name="turns">要转换的属性</param>
                public CustomContractResolver(string[] retain = null, string[] ignore = null, IDictionary<string, string> turns = null)
                {
                    // 指定要序列化属性的清单
                    this.retain = retain;
                    // 指定要忽略属性的清单
                    this.ignore = ignore;
                    // 指定要转换名称属性的清单
                    this.turns = turns;
                }

                /// <summary>
                /// 重写属性创建函数
                /// </summary>
                /// <param name="type">对象类型</param>
                /// <param name="memberSerialization">成员序列化对象</param>
                /// <returns>成员属性集合</returns>
                protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
                {
                    List<JsonProperty> list = base.CreateProperties(type, memberSerialization).ToList();

                    if (retain != null)
                    {
                        // 只保留清单有列出的属性
                        list = list.Where(p => retain.Contains(p.PropertyName)).ToList();
                    }

                    if (ignore != null)
                    {
                        // 只保留清单有列出的属性
                        list = list.Where(p => !ignore.Contains(p.PropertyName)).ToList();
                    }

                    if (turns != null)
                    {
                        // 修改需要修改名称的属性
                        foreach (var turn in turns)
                        {
                            list.ForEach(new Action<JsonProperty>((m) =>
                            {
                                if (m.PropertyName == turn.Key)
                                {
                                    m.PropertyName = turn.Value;
                                }
                            }));
                        }
                    }

                    return list;
                }
            }


        }
    }
